package edu.amm.fanal.ui;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import edu.amm.fanal.api.NonlinearProblem;
import edu.amm.fanal.examples.NonlinearProblemsExamples;
import edu.amm.fanal.ui.GraphicsFormController.GraphicData;

/**
 * Запускает приложение.
 * 
 * @author Иванов Илья
 * @since 2013-05-19
 *
 */
public class SolverApplication extends Application {
	
	private Stage dataInputForm;
	private Stage graphicsForm;
	
	private GraphicsFormController graphicsController;
	
	public SolverApplication() {
		solver = this;
	}
	
	public void start(Stage primaryStage) throws Exception {
		dataInputForm = loadDataInputForm(primaryStage);
		dataInputForm.show();
	}
	
	public void closeDataInputForm() {
		if (graphicsForm == null)
			exit();
		else {
			dataInputForm.hide();
			if (!graphicsForm.showingProperty().get())
				graphicsForm.show();
		}
	}
	
	public void showDataInputForm() {
		if (dataInputForm == null || dataInputForm.showingProperty().get())
			return;
		
		dataInputForm.show();
	}
	
	public void showGraphic(GraphicData graphic) {
		if (graphic == null)
			return;
		if (graphicsForm == null)
			graphicsForm = loadGraphicsForm();
		if (graphicsForm == null)
			return;
		
		if (!graphicsForm.showingProperty().get())
			graphicsForm.show();
		
		closeDataInputForm();
		graphicsController.showGraphic(graphic);
	}
	
	private Stage loadDataInputForm(Stage stage) throws Exception {
		FXMLLoader loader = new FXMLLoader(getClass().getResource(DATA_INPUT_FORM_FXML));
		Parent root = (Parent) loader.load();
		
		final DataInputFormController controller = loader.<DataInputFormController>getController();
		stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
			
			public void handle(WindowEvent event) {
				controller.stopCalculations();
			}
		});
		
		Scene scene = new Scene(root);
		stage.setScene(scene);
		stage.setTitle(DATA_INPUT_FORM_TITLE);
		stage.setResizable(false);
		
		return stage;
	}
	
	private Stage loadGraphicsForm() {
		Stage stage = null;
		try {
			FXMLLoader loader = new FXMLLoader(getClass().getResource(GRAPHICS_FORM_FXML));
			Parent root = (Parent) loader.load();
			graphicsController = loader.<GraphicsFormController>getController();
			
			Scene scene = new Scene(root);
			stage = new Stage();
			stage.setScene(scene);
			stage.setTitle(GRAPHICS_FORM_TITLE);
		} catch (Throwable e) {
			log.fatal("Невозможно загрузить форму для отображения графиков", e);
		}
		
		return stage;
	}
	
	private static final String LOGGING_PROPERTIES = "edu/amm/fanal/logging.properties";
	
	private static final String APP_NAME = "Решение краевой задачи";
	
	private static final String DATA_INPUT_FORM_FXML = "DataInputForm.fxml";
	private static final String DATA_INPUT_FORM_TITLE = APP_NAME + " - Настройка методов";
	
	private static final String GRAPHICS_FORM_FXML = "GraphicsForm.fxml";
	private static final String GRAPHICS_FORM_TITLE = APP_NAME + " - Графики";
	
	private static SolverApplication solver;
	private static Logger log = Logger.getLogger(SolverApplication.class);
	
	public static void main(String[] args) {
		try {
			PropertyConfigurator.configure(OperatorEquation.class.getClassLoader().getResource(LOGGING_PROPERTIES));
		} catch (Throwable e) {
			System.err.println("Не удаётся сконфигурировать систему логирования");
			return;
		}
		
		launch(args);
	}
	
	public static SolverApplication getApplication() {
		return solver;
	}
	
	public static NonlinearProblem getExample() {
		return NonlinearProblemsExamples.EXAMPLE_2;
	}
	
	public static void exit() {
		Platform.exit();
	}
}